home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.sys.amiga.programmer
- Path: dd.chalmers.se!news.chalmers.se!sunic!trane.uninett.no!eunet.no!nuug!EU.net!howland.reston.ans.net!usenet.ins.cwru.edu!eff!news.duke.edu!concert!sas!mozart.unx.sas.com!walker
- From: walker@twix.unx.sas.com (Doug Walker)
- Subject: Re: Help - Boopsi
- Originator: walker@twix.unx.sas.com
- Sender: news@unx.sas.com (Noter of Newsworthy Events)
- Message-ID: <CpwKKB.D6B@unx.sas.com>
- Date: Mon, 16 May 1994 16:02:35 GMT
- References: <44798@mindlink.bc.ca>
- Nntp-Posting-Host: twix.unx.sas.com
- Organization: SAS Institute Inc.
- Lines: 108
-
-
- In article <44798@mindlink.bc.ca>, Dave_Thomas@mindlink.bc.ca (Dave Thomas) writes:
- |> I was having exactly the same problem. When I read this message, I got so
- |> excited I just had to log-off and try it, and, lo & behold, it worked!
- |> Now, the next question is, can anyone explain this to me? Tell me if this
- |> is what's happening: whenever the dispatcher is called, the program is
- |> saving variables, addresses, etc. on the stack, and since the dispatcher is
- |> called quite often, the program runs out of stack space. If this is the
- |> case, and we're turning off stack checking, isn't the program going to
- |> write past the end of the stack and corrupt some other part of memory? Is
- |> this safe?
- |>
- |> Thanks for your help!
-
- OK, here's a general discussion of stacks, stack checking, and
- callback routines, since I've answered similar questions frequently
- in the past couple of months. Note that the discussion applies to
- BOOPSI callbacks, software interrupts, input event handlers, shared
- libraries, and lots of other callback-type situations.
-
- As functions get called, they require space for local variables,
- parameters, and compiler work space. The amount needed varies
- for different function, but it's always the same for the same
- function: i.e. if you call function foo() four times, the amount
- of stack needed is the same for each call.
-
- When functions return, all the stack space they use is made
- available for other functions to use. After the return(),
- the function isn't using any stack. Therefore, it doesn't
- matter how many times the dispatcher is called - it will never
- use any more stack than the first time, assuming it doesn't
- call itself recursively.
-
- One more thing to note: each task in the Amiga OS has its own stack.
- When BOOPSI calls your function, it calls your code from BOOPSI's task
- context; this means that your function is using BOOPSI's stack during
- that call. This becomes important when you realize how stack checking
- works.
-
- How Stack Checking Works:
-
- When the program starts up, the startup code (c.o or equivalent)
- makes a note of the lowest valid address in the stack. The stack
- pointer is set to a value in the high end of the stack, and gets
- smaller as more data is added.
-
- At the beginning of each function, the compiler generates code to
- compare the current stack pointer with the minimum stack location
- that the startup code stored. If the difference is smaller than
- the amount of stack required for the current function, it aborts the
- program. (If you're using stack EXTENSION instead of stack CHECKING,
- it actually allocates a new stack for you instead of aborting.)
-
- Now, putting two and two together, we see that stack checking will only
- work for one task's stack. Why? Because we're assuming that we know
- the correct minimum stack value. Since BOOPSI calls you on BOOPSI's
- stack, we don't know this correct value, and there is no way that stack
- checking (or stack extension) can work!
-
- You mention that your dispatcher stores values on the stack, so you're
- worried that stack checking is necessary. As long as you make sure
- that your function doesn't allocate very much stack (a couple of
- hundred bytes at most) then you will be OK. Your function will
- allocate stack for all AUTOMATIC variables and function parameters.
- Static and extern variables are fine.
-
- Speaking of static and extern variables, there is one other gotcha with
- callbacks: the near data register.
-
- Register A4 is usually set up by the compiler to point to your global
- data. The compiler generates code to access the global data relative
- to register A4 instead of at an absolute memory address. There are
- several advantages to this, including smaller code, faster code, and
- reentrant code (code that can be part of several processes at the
- same time.)
-
- When BOOPSI calls your callback function, it does not set up register
- A4 for you. You have to make sure it is set up if you want to use it.
- There are many solutions to this problem, including the following:
-
- 1. If you don't care about using near data, compile with DATA=FAR.
- This will eliminate the use of register A4 for global data.
-
- 2. If your program was not linked with cres.o, declare your BOOPSI
- callback with the __saveds keyword. This will force the compiler
- to generate code to load A4 at the start of the function. This
- will not work from cres.o programs.
-
- 3. From cres.o programs, pass the correct A4 value as your UserData
- parameter. Get its value with the "getreg()" function (defined
- in <dos.h>):
-
- long UserData = getreg(REG_A4);
-
- once you receive it in your callback, put it with putreg:
-
- putreg(REG_A4, UserData);
-
- Note that "string literals" are also global data, so you may need
- global data in places that you don't think you do...
- --
- ***** / walker@unx.sas.com
- *|_o_o|\\ Doug Walker< BIX, Portal: djwalker
- *|. o.| || \ CompuServe: 71165,2274
- | o |//
- ======
- Any opinions expressed are mine, not those of SAS Institute, Inc.
-